import { App, computed, defineComponent, getCurrentInstance, PropType, StyleValue, VNodeChild } from "vue"
import { getComponent } from "../_util/props-util"
import Icon from "../icon"

const preCls = 'x-progress'

const Progress = defineComponent({
  name: preCls,
  props: {
    percent: { type: Number, default: 0 },
    color: [String, Object, Function],
    strokeWidth: { type: Number, default: 8 },
    railColor: [String, Object, Function],
    railStyle: [String, Object, Array] as PropType<StyleValue>,
    status: { type: String as PropType<'default' | 'success' | 'error' | 'warning'>, default: 'default' },
    textInside: Boolean,
    showText: { type: Boolean, default: true },
    format: Function as PropType<(percent: number) => VNodeChild>
  },
  setup(props) {
    const { proxy: vm } = getCurrentInstance()

    const iconMap = {
      success: 'check-circle',
      error: 'close-circle',
      warning: 'info-circle'
    }

    function getStatus() {
      return props.percent >= 100 ? 'success' : props.status
    }

    function getText() {
      if (!props.showText) return
      const status = getStatus()
      const clazz = `${preCls}_text`
      const text = getComponent(vm, 'format', props.percent), mergeText = text || (props.percent + '%');
      if (props.textInside || text || status === 'default') {
        return <span class={clazz}>{ mergeText }</span>
      } else {
        return <Icon class={clazz} type={iconMap[status]} />
      }
    }

    function getColor(color) {
      if (!color) return
      switch (typeof color) {
        case 'string': return color
        case 'object': return Object.entries(color).sort((a, b) => +b[0] - +a[0]).find(e => props.percent >= +e[0])?.[1]
        case 'function': return color(props.percent)
      }
    }

    const colorRef = computed(() => getColor(props.color))
    const railColorRef = computed(() => getColor(props.railColor))

    return () => {
      const { percent, textInside, strokeWidth, railStyle } = props
      const _percent = Math.min(100, Math.max(0, percent))
      const color = colorRef.value, railColor = railColorRef.value
      const clazz = [preCls, `${preCls}-status-${getStatus()}`, {
        [`${preCls}-text-inside`]: textInside,
      }]

      return (
        <div class={clazz}>
          <div class={`${preCls}_rail`} style={[railStyle, { background: railColor }]}>
            <div class={`${preCls}_fill`} style={{ width: `${_percent}%`, minHeight: `${strokeWidth}px`, background: color }}>{ textInside && getText() }</div>
          </div>
          { textInside || getText() }
        </div>
      )
    }
  }
})

Progress.install = (app: App) => {
  app.component(Progress.name, Progress)
}

export default Progress